<template>
  <div class="job-recommend">
    <!-- 页头与筛选栏 -->
    <div class="panel header-panel">
      <div class="tools">
          <div class="spacer"></div>
          <div class="scroll-selects">
            <!-- 职位：左右拉框（上） -->
            <div class="scroll-row">
              <button class="arrow-btn" @click="scrollRow('type', -1)" aria-label="prev-type">&lt;</button>
              <div class="chip-list" ref="typeScroll">
                <button
                  v-for="opt in typeOptions"
                  :key="opt.value"
                  :class="['chip', { active: (filters.type || 'all') === opt.value }]"
                  @click="onSelectType(opt.value, opt.label)">
                  {{ opt.label }}
                </button>
              </div>
              <button class="arrow-btn" @click="scrollRow('type', 1)" aria-label="next-type">&gt;</button>
            </div>
            <!-- 城市：左右拉框（下） -->
            <div class="scroll-row">
              <button class="arrow-btn" @click="scrollRow('city', -1)" aria-label="prev-city">&lt;</button>
              <div class="chip-list" ref="cityScroll">
                <button
                  v-for="c in cityOptions"
                  :key="c.value"
                  :class="['chip', { active: filters.city === c.value }]"
                  @click="onSelectCity(c.value)">
                  {{ c.label }}
                </button>
              </div>
              <button class="arrow-btn" @click="scrollRow('city', 1)" aria-label="next-city">&gt;</button>
            </div>
          </div>
        </div>
    </div>

    <!-- 列表区域 -->
    <div class="panel" ref="listPanel">
      <div class="p-title">{{ listTitle }}</div>
      <div class="p-content" ref="listContent">
        <el-skeleton v-if="loading" :rows="6" animated />
        <div v-else class="card-grid">
          <div v-for="(item,idx) in list" :key="item.jobId || idx" :class="['card', { liked: likes[item.jobId]?.isLike, favorited: favorites[item.jobId]?.isFavorite }]">
            <div class="header">
              <div class="title" :title="item.company">{{ item.company }}</div>
              <span class="badge-salary">{{ item.salary }}</span>
            </div>
            <div class="loc" :title="item.location">{{ item.location }}</div>
            <div class="actions">
              <el-button size="small" type="primary" class="btn-primary" @click="openJob(item)">查看职位</el-button>
              <el-button
                size="small"
                class="btn-icon"
                :class="{ active: likes[item.jobId]?.isLike }"
                :disabled="!item.jobId"
                @click="likeJob(item)"
                title="点赞"
              >
                <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                  <path d="M14 9V5a3 3 0 0 0-3-3l-1 6M7 12H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h2m0-7v7m0-7h7.5a2 2 0 0 1 1.94 2.47l-1.1 4.4A2 2 0 0 1 13.4 20H7"/>
                </svg>
                <span class="num">{{ likes[item.jobId]?.liked ?? 0 }}</span>
              </el-button>
              <el-button size="small" class="btn-icon" :class="{ active: favorites[item.jobId]?.isFavorite }" @click="favoriteJob(item)" title="收藏">
                <svg class="icon" viewBox="0 0 24 24" :fill="favorites[item.jobId]?.isFavorite ? 'currentColor' : 'none'" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                  <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/>
                </svg>
                <span class="num">{{ favorites[item.jobId]?.favorited ?? 0 }}</span>
              </el-button>
              
            </div>
          </div>
          <div v-if="!list.length" class="empty">暂无数据</div>
        </div>
        <div class="pager" ref="pager">
          <el-pagination
            background
            layout="prev, pager, next"
            :page-size="page.pageSize"
            :total="page.total"
            :current-page="page.pageNum"
            @current-change="onPage"/>
        </div>
      </div>
    </div>

    <!-- 图表区域移除：按需求不展示 -->
  </div>
</template>

<script>
// 图表已移除
import { getJobKeywords, getJobListByType, getJobLikes, toggleJobLike, getJobFavorites, toggleJobFavorite } from '@/api/jobApi'
import { ElMessage } from 'element-plus'

export default {
  name: 'JobRecommend',
  data(){
    return {
      keywords: [],
      cities: ['北京','上海','广州','深圳','杭州','成都','重庆','武汉','西安','长沙','郑州','长春','贵阳','宁波'],
      filters: { type: null, city: '' },
      list: [],
      page: { pageNum: 1, pageSize: 12, total: 0 },
      loading: false,
      likes: {},
      favorites: {},
      selectedTypeLabel: null
    }
  },
  computed: {
    listTitle(){
      if (this.filters.type === 'recommend') return '猜你喜欢'
      const label = this.listTypeLabel()
      return `${label}职位列表`
    },
    // 上方职位滚动选项（带“全部”）
    typeOptions(){
      const base = [{ label: '猜你喜欢', value: 'recommend' }]
      return base.concat(this.keywords || [])
    },
    // 城市滚动选项（带“全部城市”）
    cityOptions(){
      const all = [{ label: '全部城市', value: '' }]
      return all.concat((this.cities || []).map(x=>({ label: x, value: x })))
    }
  },
  mounted(){
    this.loadKeywords()
    this.autoFitPageSize()
    this.reload()
    console.log('[JobRecommend] mounted, will fetch likes after list loaded')
    window.addEventListener('resize', this.onResize)
  },
  beforeUnmount(){
    window.removeEventListener('resize', this.onResize)
  },
  methods:{
    mapLabelToType(label){
      const s = String(label || '').trim().toLowerCase()
      if (!s) return 'java'
      if (s === 'java') return 'java'
      if (s.includes('前端')) return 'front'
      if (s.includes('后端')) return 'back'
      if (s === 'c' || s === 'c/c++/c#' || s === 'c/c++' || s === 'c#' || s === 'c++') return 'c'
      if (s === 'go' || s === 'golang') return 'go'
      if (s === 'javascript' || s === 'js') return 'javascript'
      if (s === 'nodejs' || s === 'node' || s === 'nodejs开发' || s === 'nodejs工程师') return 'nodejs'
      if (s.includes('测试')) return 'test'
      if (s === 'python') return 'python'
      if (s.includes('运维')) return 'operations'
      if (s === 'web' || s === '全栈' || s === 'fullstack' || s === 'full-stack') return 'web'
      return 'java'
    },
    listTypeLabel(){
      const map = {
        'java':'Java','front':'前端','back':'后端','c':'C/C++/C#','go':'Golang','javascript':'JavaScript','nodejs':'NodeJS','test':'测试','python':'Python','operations':'运维','web':'全栈','all':'全部'
      }
      return map[this.filters.type || 'all'] || '全部'
    },
    onSelectType(val, label){
      // 切换职位类型并刷新；记住显示标签
      this.filters.type = val
      this.selectedTypeLabel = label
      this.reload()
    },
    onSelectCity(val){
      // 切换城市并刷新
      this.filters.city = val
      this.reload()
    },
    scrollRow(which, dir){
      const refEl = which === 'type' ? this.$refs.typeScroll : this.$refs.cityScroll
      if(!refEl) return
      const distance = Math.max(120, Math.floor(refEl.clientWidth * 0.6))
      const delta = dir > 0 ? distance : -distance
      this.smoothScroll(refEl, delta, 220)
    },
    smoothScroll(el, delta, duration = 200){
      const start = el.scrollLeft
      const end = start + delta
      const startTime = performance.now()
      const animate = (now)=>{
        const t = Math.min(1, (now - startTime) / duration)
        const eased = t < 0.5 ? 2*t*t : -1 + (4 - 2*t)*t // easeInOut
        el.scrollLeft = start + (end - start) * eased
        if (t < 1) requestAnimationFrame(animate)
      }
      requestAnimationFrame(animate)
    },
    async loadKeywords(){
      const r = await getJobKeywords()
      if (r && r.code === 200) {
        // 将后端关键词映射为后端期望的 type 值（容错大小写/空格/同义词）
        this.keywords = (r.data || []).map(x=>({ label: x.label, value: this.mapLabelToType(x.label) }))
      }
    },
    async reload(){
      this.page.pageNum = 1
      await this.fetchList()
    },
    async onPage(p){
      this.page.pageNum = p
      await this.fetchList()
    },
    async fetchList(){
      try{
        this.loading = true
        const apiType = this.filters.type === 'recommend' ? 'all' : (this.filters.type || 'all')
        const params = { type: apiType, city: this.filters.city, pageNum: this.page.pageNum, pageSize: this.page.pageSize }
        const r = await getJobListByType(params)
        if (r && r.code === 200){
          this.list = r.data.records || []
          this.page.total = r.data.total || 0
          console.log('[JobRecommend] list loaded:', this.list.map(i=>({id:i.jobId,type:i.type})))
          // 批量加载当前页每个职位的点赞与收藏信息
          await Promise.all([this.fetchLikesBatch(), this.fetchFavoritesBatch()])
        }
      } finally {
        this.loading = false
      }
    },
    async fetchLikesBatch(){
      const tasks = (this.list || []).map(it => this.loadLike(it))
      await Promise.all(tasks)
    },
    async fetchFavoritesBatch(){
      const tasks = (this.list || []).map(it => this.loadFavorite(it))
      await Promise.all(tasks)
    },
    async loadLike(item){
      try{
        const typeForLike = (this.filters.type === 'recommend') ? 'all' : (this.filters.type || 'java')
        const itemType = item.type || typeForLike
        const r = await getJobLikes(item.jobId, { params: { type: itemType }})
        if (r && r.code === 200){ this.$set ? this.$set(this.likes, item.jobId, r.data) : (this.likes[item.jobId] = r.data) }
      }catch(e){ /* ignore */ }
    },
    async likeJob(item){
      try{
        const typeForLike = (this.filters.type === 'recommend') ? 'all' : (this.filters.type || 'java')
        console.log('[JobRecommend] like click:', item.jobId, item.type || typeForLike)
        const itemType = item.type || typeForLike
        const r = await toggleJobLike(item.jobId, { params: { type: itemType }})
        if (r && r.code === 200){
          await this.loadLike(item)
        }
      }catch(e){
        // 未登录情况下，后端返回401，由响应拦截器跳转登录
      }
    },
    async loadFavorite(item){
      try{
        const typeForFav = (this.filters.type === 'recommend') ? 'all' : (this.filters.type || 'java')
        const itemType = item.type || typeForFav
        const r = await getJobFavorites(item.jobId, { params: { type: itemType }})
        if (r && r.code === 200){ this.$set ? this.$set(this.favorites, item.jobId, r.data) : (this.favorites[item.jobId] = r.data) }
      }catch(e){ /* ignore */ }
    },
    async favoriteJob(item){
      try{
        const typeForFav = (this.filters.type === 'recommend') ? 'all' : (this.filters.type || 'java')
        const itemType = item.type || typeForFav
        const r = await toggleJobFavorite(item.jobId, { params: { type: itemType }})
        if (r && r.code === 200){ await this.loadFavorite(item) }
      }catch(e){
        // 未登录情况下，后端返回401，由响应拦截器跳转登录
      }
    },
    openJob(row){
      if(row && row.jobDetailUrl){ window.open(row.jobDetailUrl,'_blank') }
    },
    goHome(){
      this.$router.push({ name: 'Home' })
    },
    onResize(){
      this.autoFitPageSize(false)
    },
    autoFitPageSize(reload = false){
      // 计算能铺满屏幕的卡片数量：列数 * 行数
      this.$nextTick(()=>{
        const content = this.$refs.listContent
        if(!content) return
        const pager = this.$refs.pager
        const contentHeight = content.clientHeight || 0
        const pagerHeight = pager ? pager.clientHeight : 0
        const available = Math.max(0, contentHeight - pagerHeight - 12)
        // 估算卡片高度与间距（与样式保持一致）
        const cardHeight = 140
        const gap = 12
        const rows = Math.max(1, Math.floor((available + gap) / (cardHeight + gap)))
        const width = window.innerWidth
        let cols = 4
        if (width <= 640) cols = 1
        else if (width <= 1024) cols = 2
        else if (width <= 1400) cols = 3
        const pageSize = Math.max(4, rows * cols)
        if (pageSize !== this.page.pageSize){
          this.page.pageSize = pageSize
          if (reload) this.reload();
        }
      })
    },
    // 图表相关逻辑已移除
  }
}
</script>

<style scoped>
.job-recommend{ padding: 0.3rem; color:#fff; background: linear-gradient(180deg, rgba(1,14,80,.85), rgba(1,14,80,.95)), url(@/assets/images/bg.jpg) center top no-repeat; background-size: cover; height:100vh; display:grid; grid-template-rows:auto 1fr; grid-template-columns:1fr }
.w-180{ width:180px }
.w-160{ width:160px }
.panel{ border: 1px solid rgba(100, 162, 255, .25); position: relative; background: rgba(0, 35, 120, .36); display:flex; flex-direction:column; margin-bottom: 0.3rem; backdrop-filter: blur(4px) }
.panel:after, .panel:before { position: absolute; content: ""; width: 20px; height: 30px }
.panel:before { border-left: 1px solid #0258f0; border-top: 1px solid #0258f0; left: -1px; top: -1px }
.panel:after { border-right: 1px solid #0258f0; border-bottom: 1px solid #0258f0; right: -1px; bottom: -1px }
.p-title{ height: 36px; font-size: 16px; line-height: 36px; width:100%; font-weight:600; padding: 0 15px; position:relative; display:flex; justify-content:space-between; align-items:center; letter-spacing:.5px }
.p-title:after{ position:absolute; content:""; width:20%; height:1px; background:#0258f0; left:5%; opacity:.4; bottom:0 }
.p-content{ flex-grow:1; margin: 0.2rem; position:relative; overflow:auto }
.header-panel .tools{ display:flex; gap:12px; align-items:center; width:100%; justify-content:center }
.header-panel .tools .spacer{ display:none }
.ml-auto{ margin-left:auto }

/* 左右拉框（上下两行） */
.scroll-selects{ display:flex; flex-direction:column; gap:8px; min-width: 520px }
.scroll-row{ display:flex; align-items:center; gap:8px }
.arrow-btn{ width:36px; height:28px; line-height:28px; text-align:center; border:1px solid rgba(100,162,255,.6); background:rgba(255,255,255,.06); color:#dbeafe; cursor:pointer; border-radius:0 }
.arrow-btn:hover{ background: rgba(2,88,240,.15); border-color:#63a2ff; color:#fff }
.chip-list{ display:flex; gap:10px; overflow:hidden; white-space:nowrap; flex:1 1 auto; padding:2px }
.chip{ height:28px; padding:0 12px; border-radius:0; border:1px solid rgba(100,162,255,.6); background:rgba(255,255,255,.06); color:#dbeafe; cursor:pointer; display:inline-flex; align-items:center }
.chip:hover{ background: rgba(2,88,240,.15); border-color:#63a2ff; color:#fff }
.chip.active{ background: rgba(2,88,240,.15); border-color:#63a2ff; color:#fff }

.card-grid{ display:grid; grid-template-columns: repeat(4, 1fr); gap: 12px }
.card{ border:1px solid rgba(100,162,255,.25); border-radius:8px; padding:12px; background: radial-gradient(120% 120% at 0% 0%, rgba(10,40,120,.35), rgba(0,35,120,.2)); display:flex; flex-direction:column; gap:10px; min-height:140px; transition: all .25s ease }
.card:hover{ border-color:#63a2ff; box-shadow: 0 6px 18px rgba(2,88,240,.25); transform: translateY(-2px) }
.header{ display:flex; justify-content:space-between; align-items:center; gap:8px }
.title{ font-weight:600; white-space:nowrap; text-overflow:ellipsis; overflow:hidden; max-width:70% }
.badge-salary{ color:#0b1a39; background: #9fd0ff; border-radius: 999px; padding: 2px 8px; font-size: 12px; font-weight:700 }
.loc{ color:#cfe2ff; opacity:.9 }
.actions{ margin-top:auto; display:flex; gap:8px; flex-wrap:wrap }
.empty{ color:#cfe2ff; opacity:.8 }
.pager{ display:flex; justify-content:center; margin: 10px 0 }

/* 统一按钮视觉到项目风格 */
.job-recommend :deep(.el-button--primary){
  background: rgba(2, 88, 240, 0.9);
  border-color: rgba(100, 162, 255, 0.8);
}
.job-recommend :deep(.el-button--primary:hover){
  filter: brightness(1.05);
}

/* 统一下拉框视觉到按钮风格 */
.job-recommend :deep(.el-select .el-input__wrapper){
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(100,162,255,.6);
  box-shadow: none;
}
.job-recommend :deep(.el-select .el-input__wrapper.is-focus),
.job-recommend :deep(.el-select .el-input__wrapper:hover){
  background: rgba(2,88,240,.15);
  border-color: #63a2ff;
}
.job-recommend :deep(.el-select .el-input__inner){
  color: #dbeafe;
}
.job-recommend :deep(.el-select .el-select__caret){
  color: #cfe2ff;
}
.job-recommend :deep(.el-select-dropdown){
  background: rgba(0, 35, 120, .96);
  border: 1px solid rgba(100,162,255,.25);
}
.job-recommend :deep(.el-select-dropdown__item){
  color: #dbeafe;
}
.job-recommend :deep(.el-select-dropdown__item.hover),
.job-recommend :deep(.el-select-dropdown__item.selected){
  background: rgba(2,88,240,.15);
  color: #fff;
}

/* 统一分页视觉到按钮风格 */
.job-recommend :deep(.el-pagination.is-background .btn-prev),
.job-recommend :deep(.el-pagination.is-background .btn-next),
.job-recommend :deep(.el-pagination.is-background .el-pager li){
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(100,162,255,.6);
  color: #cfe2ff;
}
.job-recommend :deep(.el-pagination.is-background .el-pager li.is-active),
.job-recommend :deep(.el-pagination.is-background .btn-prev:hover),
.job-recommend :deep(.el-pagination.is-background .btn-next:hover),
.job-recommend :deep(.el-pagination.is-background .el-pager li:hover){
  background: rgba(2,88,240,.15);
  border-color: #63a2ff;
  color: #fff;
}

/* 自定义按钮款式 */
.btn-outline{ background: transparent; border:1px solid rgba(100,162,255,.6); color:#cfe2ff }
.btn-outline:hover{ background: rgba(2,88,240,.15); border-color:#63a2ff; color:#fff }
.btn-ghost{ background: rgba(255,255,255,.06); border:1px solid transparent; color:#dbeafe }
.btn-ghost:hover{ background: rgba(255,255,255,.12) }

/* 图标按钮（点赞/收藏） */
.btn-icon{ background: transparent; border:1px solid rgba(100,162,255,.6); color:#cfe2ff; display:inline-flex; align-items:center; gap:8px }
.btn-icon:hover{ background: rgba(2,88,240,.15); border-color:#63a2ff; color:#fff }
.btn-icon .icon{ width:18px; height:18px }
.btn-icon .num{ font-weight:600 }
.btn-icon.active{ color:#63a2ff; border-color:#63a2ff; background: rgba(2,88,240,.10) }

/* 响应式列数调整 */
@media (max-width: 1400px){
  .card-grid{ grid-template-columns: repeat(3, 1fr) }
}
@media (max-width: 1024px){
  .card-grid{ grid-template-columns: repeat(2, 1fr) }
}
@media (max-width: 640px){
  .card-grid{ grid-template-columns: repeat(1, 1fr) }
}

/* 图表区域已移除 */
</style>


